package com.acooly.module.openapi.client.provider.newyl.support;

import com.acooly.core.utils.security.RSA;
import com.acooly.module.safety.exception.SafetyException;
import com.acooly.module.safety.exception.SafetyResultCode;
import com.acooly.module.safety.support.CodecEnum;
import com.acooly.module.safety.support.KeySupport;

import org.apache.commons.io.IOUtils;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;

import java.io.InputStream;
import java.io.ObjectInputStream;
import java.security.PrivateKey;
import java.security.PublicKey;

import lombok.extern.slf4j.Slf4j;

/**
 * @author zhike 2018/2/6 13:47
 * .key文件加载
 */
@Slf4j
public class NewYlKeyStoreInfo extends KeySupport {

    public static final String KEY_STORE_PKCS12 = "PKCS12";

    private String keyStoreType = KEY_STORE_PKCS12;

    /**
     * 对方的公钥
     */
    private String privateKeyUrl;
    /**
     * 自己的私钥
     */
    private String publicKeyUrl;

    /**
     * 签名结果字符串编码
     */
    private CodecEnum signatureCodec = CodecEnum.BASE64;

    private String signatureAlgo = RSA.SIGN_ALGO_MD5;

    /**
     * 签名明文字符串编码
     */
    private String plainEncode = "GBK";


    private PrivateKey privateKey;

    private PublicKey publicKey;

    public NewYlKeyStoreInfo loadKeys() {
        if (privateKey == null) {
            synchronized (this) {
                if (privateKey == null) {
                    loadPrivateKey();
                }
            }
        }
        if (publicKey == null) {
            synchronized (this) {
                if (publicKey == null) {
                    loadCertificate();
                }
            }
        }
        return this;
    }

    protected void initKey() {
        loadPrivateKey();
        loadCertificate();
    }

    private void loadPrivateKey() {
        InputStream in = null;
        try {
            Resource resource = new DefaultResourceLoader().getResource(getPrivateKeyUrl());
            in = resource.getInputStream();
            ObjectInputStream objectInputStream = new ObjectInputStream(in);
            PrivateKey privateKey = (PrivateKey)objectInputStream.readObject();
            this.privateKey = privateKey;
            log.debug("加载keystore私钥 - [成功] , privateKey:{}", this.privateKey);
        } catch (Exception e) {
            log.warn("加载keystore私钥 - [失败] , 原因: {}", e.getMessage());
            throw new SafetyException(SafetyResultCode.LOAD_KEYSTORE_PRIVATE_ERROR, e.getMessage());
        } finally {
            IOUtils.closeQuietly(in);
        }
    }

    private void loadCertificate() {
        InputStream in = null;
        try {
            Resource resource = new DefaultResourceLoader().getResource(getPublicKeyUrl());
            in = resource.getInputStream();
            ObjectInputStream objectInputStream = new ObjectInputStream(in);
            PublicKey publicKey = (PublicKey)objectInputStream.readObject();
            this.publicKey = publicKey;
            log.debug("加载证书 - [成功] , cert:{}", publicKey);
        } catch (Exception e) {
            log.warn("加载证书 - [失败] , 原因: {}", e.getMessage());
            throw new SafetyException(SafetyResultCode.LOAD_CERTIFICATE_ERROR, e.getMessage());
        } finally {
            IOUtils.closeQuietly(in);
        }
    }

    public String getPrivateKeyUrl() {
        return privateKeyUrl;
    }

    public void setPrivateKeyUrl(String privateKeyUrl) {
        this.privateKeyUrl = privateKeyUrl;
    }

    public String getPublicKeyUrl() {
        return publicKeyUrl;
    }

    public void setPublicKeyUrl(String publicKeyUrl) {
        this.publicKeyUrl = publicKeyUrl;
    }

    public PrivateKey getPrivateKey() {
        return privateKey;
    }

    public void setPrivateKey(PrivateKey privateKey) {
        this.privateKey = privateKey;
    }

    public String getPlainEncode() {

        return plainEncode;
    }

    public void setPlainEncode(String plainEncode) {
        this.plainEncode = plainEncode;
    }

    public PublicKey getPublicKey() {
        return publicKey;
    }

    public void setPublicKey(PublicKey publicKey) {
        this.publicKey = publicKey;
    }

    public String getSignatureAlgo() {
        return signatureAlgo;
    }

    public void setSignatureAlgo(String signatureAlgo) {
        this.signatureAlgo = signatureAlgo;
    }

    public CodecEnum getSignatureCodec() {
        return signatureCodec;
    }

    public void setSignatureCodec(CodecEnum signatureCodec) {
        this.signatureCodec = signatureCodec;
    }

    public String getKeyStoreType() {
        return keyStoreType;
    }

    public void setKeyStoreType(String keyStoreType) {
        this.keyStoreType = keyStoreType;
    }
}
